import config
import os
import copy
import update

def draw_field():   
    if update.number_step / update.current_size**2 >= 0.2:
        update.current_size = min(update.max_size, update.current_size + 1)

    print('{:>4}'.format(''), end='')
    for i in range(update.current_size):
        print(config.X_axis[i], end=' ')

    print()
    for i in range(update.current_size):
        print('{:<4}'.format(config.Y_axis[i]), end='')
        for j in range(update.current_size):
            if (j+1) % update.current_size == 0:
                print(update.field[i][j])
            else:
                print(update.field[i][j], end=' ')

def check_win(coord, player, mod):
    if mod == 1:
        limit_l = -2
        limit_r = 3
        len_line = 3
    else :
        limit_l = -4
        limit_r = 5
        len_line = 5
        
    x = int(coord[1])-1
    y = ord(coord[0])-65
    line = ''

    if update.number_step == update.max_size**2:
        return 2
    
    line = ''.join(update.field[x][max(0, y+limit_l):min(update.current_size, y+limit_r)])
    if line.count(player*len_line) > 0:
        return 1
    
    line = ''
    for i in range(max(0, y+limit_l), min(y+limit_r, update.current_size)):
        line += update.field[i][y]    
    if line.count(player*len_line) > 0:
            return 1
    
    line = ''
    for i in range(limit_l, limit_r):
        if 0 <= x+i < update.current_size and 0 <= y+i < update.current_size:
            line += update.field[x+i][y+i]
        else:
            continue
    if line.count(player*len_line) > 0:
        return 1
    
    line = ''
    for i in range(limit_l, limit_r):
        if 0 <= x-i < update.current_size and 0 <= y+i < update.current_size:
            line += update.field[x-i][y+i]
        else:
            continue
    if line.count(player*len_line) > 0:
        return 1

    return 0
 
def process_error(coord):
    if len(coord) == 0:
        return 'Entered coordinates are incorrect, input coordinates again'
    elif len(coord) == 2:
       if (coord[0] not in config.X_axis[:update.current_size+1] and len(coord[0]) == 1) or coord[1] not in config.Y_axis[:update.current_size+1]:
            return 'Entered coordinates are incorrect, input coordinates again'

    if update.field[int(coord[1])-1][ord(coord[0])-65] != '_':
        return "This cell is't empty"
    
    return 229



def step(player):
    coord = tuple([_.upper() for _ in input("Input coordinates draw {}: ".format(player)).split()]) 
    if len(coord) == 1:
        tmp = coord[0] 
        x = tmp[0]
        y = tmp[1:]
        coord = (x, y)
    
    mess = process_error(coord)
    if mess == 229:
       update.field[int(coord[1])-1][ord(coord[0])-65] = player  
    else:
        os.system('clear')
        draw_field()
        print(mess)
        return step(player)

    update.number_step += 1
    os.system('clear')
    draw_field()
    return check_win(coord, player, update.mod)

def restart_game():
    ch = input("1. Restart Game\n0. Exit Game\n")
    if ch == '1':
        os.system('clear')
        return main()
    if ch == '0':
        os.system('clear')
        exit()
    else:
        return restart_game()

def menu():
    print('Choose game mode')
    ch = input('1. 3x3\n2. 5x5-12x12\n')
    if ch == '1':
        update.max_size = 3
        update.current_size = 3
        update.number_step = 0
        update.field = copy.deepcopy(config.field)
        update.mod = 1
    elif ch == '2':
        update.max_size = 12
        update.current_size = 5
        update.number_step = 0
        update.field = copy.deepcopy(config.field)
        update.mod = 2
    else:
        return menu()
    os.system('clear')
    
def main(): 
    menu()
    result = 0
    player = 'X' 
    draw_field()
    while result == 0:
        result = step(player)
        if player == "X" and result == 0: player = "O"
        elif player == "O" and result == 0: player = "X"
    if result == 1:
        print('We have a winner! {} win!'.format(player))
    elif result == 2:
        print('Draw')
    restart_game()
    
if __name__ == "__main__":
    main()
